using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using OpenQuarters.WebQuarters.Utils;
using System.Text;
using OpenQuarters.WebQuarters.Core;

namespace OpenQuarters.WebQuarters.Core.Web.Areas.CMS.Controllers
{
    [WorkflowItemHandlerContainer]
    public class PagesController : Controller
    {
        public ActionResult Get(string id)
        {
            ViewData.Model = Core.CMSPage.Pages.ToJSON();
            return View(Site.Helpers.SharedView.Service);
        }

        public ActionResult GetPageVersion(string id)
        {
            ViewData.Model = CMSPage.GetVersionForUser(id).ToJSON();
            return View(Site.Helpers.SharedView.Service);
        }

        public ActionResult GetPageVersions(string id)
        {
            var entries = CMSPageVersion.GetVersionsForUser(id.ToInt64());
            var sb = new StringBuilder();
            for (int i = 0; i < entries.Count; i++)
            {
                sb.Append(new CMSPageVersion.JSON(entries[i]).ToJSON());
                if (i < (entries.Count - 1))
                {
                    sb.Append(", ");
                }
            }
            ViewData.Model = "[" + sb.ToString() + "]";
            return View(Site.Helpers.SharedView.Service);
        }

        public ActionResult CopyDraft(string id)
        {
            var targetPage = CMSPage.Load(id.ToInt64());
            var resp = new Core.JFormResponse<string>();
            var version = Request.Form["version"];

            if (targetPage != null && Core.User.Current.HasPermission(Permissions.CMSPage.Edit.SetValue(targetPage.PageId.ToString())))
            {
                var draftPage = CMSPageVersion.GetVersionsFromArchive(id.ToInt64(), version.ToInt64());

                if (targetPage.DraftVersion != null)
                {
                    targetPage.DraftVersion.Delete();
                }
                var newDraftPage = targetPage.EnsureDraftVersion(targetPage.CurrentVersion.Title);

                newDraftPage.Template = draftPage.Template;
                newDraftPage.Title = draftPage.Title;
                newDraftPage.Keywords = draftPage.Keywords;
                newDraftPage.Description = draftPage.Description;
                newDraftPage.ContentDefinition = newDraftPage.ContentDefinition;

                newDraftPage = newDraftPage.Save();

                resp.result = newDraftPage.Definition;

                ViewData.Model = resp.ToJSON();
            }

            return View(Site.Helpers.SharedView.Service);
        }

        public ActionResult SaveDraft()
        {
            var targetPage = CMSPage.Load(Request.Form["id"].ToInt64());
            var resp = new JFormResponse<CMSPageVersion>();

            if (targetPage != null && Core.User.Current.HasPermission(Permissions.CMSPage.Edit.SetValue(targetPage.PageId.ToString())))
            {
                var draftPage = targetPage.EnsureDraftVersion(targetPage.CurrentVersion.Title);
                var postedPage = GeneralUtils.FromJSON<CMSPageVersion>(GeneralUtils.Base64Decode(Request.Form["pageVersion"]));

                draftPage.Template = postedPage.Template;
                draftPage.LanguageId = postedPage.LanguageId;
                draftPage.Title = postedPage.Title;
                draftPage.Keywords = postedPage.Keywords;
                draftPage.Description = postedPage.Description;
                draftPage.Tags = postedPage.Tags;
                draftPage.NoFollow = postedPage.NoFollow;
                draftPage.ContentDefinition = ContentDefinition.FromJSON(GeneralUtils.Base64Decode(Request.Form["definition"]));
                draftPage.Order = postedPage.Order;

                draftPage = draftPage.Save();

                ViewData.Model = resp.ToJSON();
            }

            return View(Site.Helpers.SharedView.Service);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult MakeLive(string id)
        {
            var resp = new JFormResponse<CMSPageVersion>();
            var version = Request.Form["version"];
            if (Core.User.Current.HasPermission(Permissions.CMSPage.Approve.SetValue(id)))
            {
                var pageVersion = CMSPageVersion.Load(Convert.ToInt64(version));
                if (pageVersion != null && !pageVersion.IsLive)
                {
                    pageVersion.MakeLive();
                    resp.result = pageVersion;
                }
            }

            ViewData.Model = resp.ToJSON();
            return View(Site.Helpers.SharedView.Service);
        }

        public ActionResult Add()
        {
            var targetPageId = Request.Form["parentId"];
            var resp = new Core.JFormResponse<Core.CMSPage>();
            if (Core.User.Current.HasPermission(Permissions.CMSPage.Create, targetPageId))
            {
                var parentPage = CMSPage.Load(Convert.ToInt64(targetPageId));
                foreach (string sTitle in Request.Form["title"].Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries))
                {
                    if (sTitle.Trim().Length > 0)
                    {
                        CMSPage addedPage = null;

                        CMSPageTemplate pageTemplate = null;
                        if (!string.IsNullOrEmpty(Request.Form["template"]))
                            pageTemplate = CMSPageTemplate.Load(Request.Form["template"].ToInt32());

                        addedPage = new CMSPage()
                        {
                            ParentId = parentPage.PageId
                        }.Save();

                        if (pageTemplate != null)
                        {
                            addedPage.LanguageId = pageTemplate.LanguageId;
                            addedPage.Save();
                        }

                        addedPage.ReplicatePermissions(parentPage);

                        var draft = addedPage.EnsureDraftVersion(sTitle.Trim()).Save();

                        if (pageTemplate != null)
                        {
                            // Set up with template defaults
                            draft.Template = pageTemplate.Template;
                            draft.Keywords = pageTemplate.Keywords;
                            draft.Description = pageTemplate.Description;
                            draft.Tags = pageTemplate.Tags;
                            draft.NoFollow = pageTemplate.NoFollow;

                            draft.Definition = pageTemplate.Definition;

                            //TODO: Override ID's

                            //Parse ContentDefinition
                            //StringBuilder sb = new StringBuilder();

                            //sb.Append("{\"Areas\": [");

                            //foreach (var area in pageTemplate.ContentDefinition.Areas)
                            //{
                            //    sb.Append("{\"Modules\": [{}");

                            //    foreach (var module in area.Modules)
                            //    {
                            //        sb.Append(",{\"ModuleType\":\"" + module.ModuleType + "\",\"ModuleJSON\":\"" + module.ModuleJSON + "\"");

                            //        sb.Append(",\"JQueryEditorName\":\"" + module.JQueryEditorName + "\",\"ModuleName\":\"\"");

                            //        sb.Append(",\"ModuleNameClassSafe\":\"" + module.ModuleNameClassSafe + "\",\"UniqueID\":\"" + module.UniqueID + "\"");

                            //       sb.Append(",\"Inherited\":" + module.IsInherited.ToString() + "}");
                            //    }

                            //    sb.Append("],\"Id\": \"" + area.Id + "\"}");
                            //}

                            //sb.Append("]}");

                            draft.Save();
                        }
                    }
                }
            }
            ViewData.Model = resp.ToJSON();
            return View(Site.Helpers.SharedView.Service);
        }

        public ActionResult Delete()
        {
            var targetPageId = Request.Form["id"];
            var resp = new Core.JFormResponse<Core.CMSPage>();
            if (!Core.User.Current.HasPermission(Permissions.CMSPage.Edit, targetPageId))
            {
                resp.errorMessages[""].Add(Core.Translation.Translate("You_do_not_have_permission_to_submit_this_page_for_deletion"));
            }
            else
            {
                var targetPage = CMSPage.Load(Convert.ToInt64(targetPageId));
                if (targetPage != null)
                {
                    var workflowItem = new WorkflowItem()
                    {
                        UserId = Core.User.Current.UserId,
                        Category = "Admin",
                        Operation = "Delete",
                        TargetType = "Page",
                        TargetName = targetPageId,
                        RequiredPermission = Permissions.CMSPage.Approve,
                        RequiredPermissionValue = targetPageId
                    }.Save();

                    var userMessage = new UserMessage()
                    {
                        UserId = Core.User.Current.UserId,
                        Category = "Admin",
                        Tags = "page, page-deletion-submission",
                        Subject = "Page '" + targetPage.Title + "' (ID " + targetPageId + ") submitted for deletion",
                        From = "admin",
                        FromName = "System",
                        Body = "You have submitted page '" + targetPage.Title + "' (ID " + targetPageId + ") for deletion.",
                        WorkflowItemId = workflowItem.WorkflowItemId
                    }.Save();

                    resp.result = targetPage;
                }
            }
            ViewData.Model = resp.ToJSON();
            return View(Site.Helpers.SharedView.Service);
        }

        [WorkflowItemHandler("Delete", "Page")]
        public static void DeletePageWorkflowHandler(WorkflowItem wi)
        {
            if (wi.json_CurrentUserHasPermission)
            {
                long pageId = Convert.ToInt64(wi.RequiredPermissionValue);
                var page = CMSPage.Load(pageId);
                if (page != null)
                {
                    // TODO: Handle soon-to-be broken links
                    page.Urls.ToList().ForEach(e => e.Delete());
                    page.CMSPageVersions.ToList().ForEach(e => e.Delete());
                    Permission.Table.Where(e => e.Name.StartsWith("CMSPage.") && e.Value == pageId.ToString()).ToList().ForEach(e => e.Delete());
                    page.Delete();
                }
            }
        }

        public ActionResult SetOrder()
        {
            var targetPageId = Request.Form["parent"];
            if (!targetPageId.IsNumeric())
            {
                targetPageId = CMSPage.LoadByReference(targetPageId).PageId.ToString();
            }
            var ordering = Request.Form["ordering"].FromJSON<List<string>>();

            var resp = new Core.JFormResponse<Core.CMSPage>();
            if (!Core.User.Current.HasPermission(Permissions.CMSPage.Order))
            {
                resp.errorMessages[""].Add(Core.Translation.Translate("You_do_not_have_permission_to_set_the_order_of_pages"));
            }
            else
            {
                var deleteItems = WorkflowItem.OpenItems.Where(e =>
                        e.UserId == Core.User.Current.UserId &&
                        e.Operation == "SetOrder" &&
                        e.TargetName == targetPageId &&
                        e.TargetType == "Page").ToList();
                foreach (var i in deleteItems)
                {
                    UserMessage.Table
                        .Where(e => e.WorkflowItemId == i.WorkflowItemId)
                        .ToList().ForEach(e => e.Delete());
                    i.Delete();
                }

                var targetPage = CMSPage.Load(targetPageId.ToInt64());
                if (targetPage != null)
                {
                    var workflowItem = new WorkflowItem()
                    {
                        UserId = Core.User.Current.UserId,
                        Category = "Admin",
                        Operation = "SetOrder",
                        Value = ordering.ToJSON(),
                        TargetType = "Page",
                        TargetName = targetPageId,
                        RequiredPermission = Permissions.CMSPage.Order

                    }.Save();

                    var userMessage = new UserMessage()
                    {
                        UserId = Core.User.Current.UserId,
                        Category = "Admin",
                        Tags = "page, page-set-order",
                        Subject = "New page order for " + targetPage.ToString(),
                        From = "admin",
                        FromName = "System",
                        Body = "You have submitted a new page order for the child pages of " + targetPage.ToString(),
                        WorkflowItemId = workflowItem.WorkflowItemId
                    }.Save();

                    resp.result = targetPage;
                }
            }
            ViewData.Model = resp.ToJSON();
            return View(Site.Helpers.SharedView.Service);
        }

        [WorkflowItemHandler("SetOrder", "Page")]
        public static void SetOrderPageWorkflowHandler(WorkflowItem wi)
        {
            if (wi.json_CurrentUserHasPermission)
            {
                var page = CMSPage.Load(wi.TargetName.ToInt64());
                if (page != null)
                {
                    int order = 0;
                    var ordering = new List<long>();
                    wi.Value.FromJSON<List<string>>().ForEach(e => ordering.Add(e.ToInt64()));
                    var pages = new FriendlyDictionary<long, List<CMSPageVersion>>();
                    CMSPageVersion.Table
                        .Where(e => ordering.Contains(e.PageId))
                        .ToList()
                        .ForEach(e => pages[e.PageId].Add(e));
                    foreach (var pageId in ordering)
                    {
                        foreach (var pageVersion in CMSPage.Load(pageId).CMSPageVersions)
                        {
                            pageVersion.Order = order;
                            pageVersion.Save();
                        }
                        order++;
                    }
                }
            }
        }

        public ActionResult GetTemplates()
        {
            ViewData.Model = Core.CMSPageTemplate.Templates.ToJSON();
            return View(Site.Helpers.SharedView.Service);
        }
    }
}
